diff --git a/django/forms/models.py b/django/forms/models.py
index c7e7e50885..8b8be56b3b 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -1248,6 +1248,8 @@ class ModelChoiceField(ChoiceField):
             return None
         try:
             key = self.to_field_name or 'pk'
+            if isinstance(value, self.queryset.model):
+                value = getattr(value, key)
             value = self.queryset.get(**{key: value})
         except (ValueError, TypeError, self.queryset.model.DoesNotExist):
             raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')
diff --git a/tests/model_forms/test_modelchoicefield.py b/tests/model_forms/test_modelchoicefield.py
index 74ef14aa73..0591c425fe 100644
--- a/tests/model_forms/test_modelchoicefield.py
+++ b/tests/model_forms/test_modelchoicefield.py
@@ -55,9 +55,18 @@ class ModelChoiceFieldTests(TestCase):
         with self.assertRaisesMessage(ValidationError, msg):
             f.clean(c4.id)
 
+    def test_clean_model_instance(self):
+        f = forms.ModelChoiceField(Category.objects.all())
+        self.assertEqual(f.clean(self.c1), self.c1)
+        # An instance of incorrect model.
+        msg = "['Select a valid choice. That choice is not one of the available choices.']"
+        with self.assertRaisesMessage(ValidationError, msg):
+            f.clean(Book.objects.create())
+
     def test_clean_to_field_name(self):
         f = forms.ModelChoiceField(Category.objects.all(), to_field_name='slug')
         self.assertEqual(f.clean(self.c1.slug), self.c1)
+        self.assertEqual(f.clean(self.c1), self.c1)
 
     def test_choices(self):
         f = forms.ModelChoiceField(Category.objects.filter(pk=self.c1.id), required=False)
@@ -194,6 +203,16 @@ class ModelChoiceFieldTests(TestCase):
         field = forms.ModelChoiceField(Author.objects.all(), disabled=True)
         self.assertIs(field.has_changed('x', 'y'), False)
 
+    def test_disabled_modelchoicefield_initial_model_instance(self):
+        class ModelChoiceForm(forms.Form):
+            categories = forms.ModelChoiceField(
+                Category.objects.all(),
+                disabled=True,
+                initial=self.c1,
+            )
+
+        self.assertTrue(ModelChoiceForm(data={'categories': self.c1.pk}).is_valid())
+
     def test_disabled_multiplemodelchoicefield(self):
         class ArticleForm(forms.ModelForm):
             categories = forms.ModelMultipleChoiceField(Category.objects.all(), required=False)