diff --git a/django/db/models/base.py b/django/db/models/base.py
index 71fd1f7..feaceee 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -382,7 +382,9 @@ class Model(object):
         return '%s object' % self.__class__.__name__
 
     def __eq__(self, other):
-        return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
+        return isinstance(other, Model) and \
+               self._meta.proxy_for_model == other._meta.proxy_for_model and \
+               self._get_pk_val() == other._get_pk_val()
 
     def __ne__(self, other):
         return not self.__eq__(other)
diff --git a/django/db/models/options.py b/django/db/models/options.py
index 6f0f406..00a5586 100644
--- a/django/db/models/options.py
+++ b/django/db/models/options.py
@@ -64,6 +64,9 @@ class Options(object):
         self.object_name = cls.__name__
         self.module_name = self.object_name.lower()
         self.verbose_name = get_verbose_name(self.object_name)
+        # Note: for convenience we set that every concrete class and abstract class
+        # is proxy of itself. This helps in __eq__ checks for example.
+        self.proxy_for_model = cls
 
         # Next, apply any overridden values from 'class Meta'.
         if self.meta:
diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt
index 0e18205..ec3324d 100644
--- a/docs/topics/db/models.txt
+++ b/docs/topics/db/models.txt
@@ -795,6 +795,15 @@ There are three styles of inheritance that are possible in Django.
     without changing the models fields in any way, you can use
     :ref:`proxy-models`.
 
+A note about model instance equality operator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When comparing the equality of model instances, Django uses the following
+rules. Two instances are considered equal if:
+
+  1. The primary keys are equal. Note that if both instances have primary key value of None, they are considered equal.
+  2. The instances are of same class. For this rule, proxy models are considered instances of the class they are proxying. Multi-table inheriting instance is not considered to be of same class with its base class.
+
 .. _abstract-base-classes:
 
 Abstract base classes
diff --git a/tests/modeltests/defer/tests.py b/tests/modeltests/defer/tests.py
index 5f6c53d..9cf32ee 100644
--- a/tests/modeltests/defer/tests.py
+++ b/tests/modeltests/defer/tests.py
@@ -23,10 +23,18 @@ class DeferTests(TestCase):
         p1 = Primary.objects.create(name="p1", value="xx", related=s1)
 
         qs = Primary.objects.all()
-
         self.assert_delayed(qs.defer("name")[0], 1)
         self.assert_delayed(qs.only("name")[0], 2)
         self.assert_delayed(qs.defer("related__first")[0], 0)
+        
+        # deferred instances are equal to their non-deferred counterpart
+        deferred_p1 = qs.defer("name")[0]
+        self.assertTrue(deferred_p1==p1)
+        # The __eq__ operator is symmetric as well as the == operator
+        self.assertTrue(p1==deferred_p1)
+        self.assertTrue(deferred_p1.__eq__(p1))
+        self.assertTrue(p1.__eq__(deferred_p1))
+
 
         obj = qs.select_related().only("related__first")[0]
         self.assert_delayed(obj, 2)
diff --git a/tests/modeltests/model_inheritance/tests.py b/tests/modeltests/model_inheritance/tests.py
index 334297a..1b19dcb 100644
--- a/tests/modeltests/model_inheritance/tests.py
+++ b/tests/modeltests/model_inheritance/tests.py
@@ -69,6 +69,16 @@ class ModelInheritanceTests(TestCase):
             StudentWorker.objects.get, pk__lt=sw2.pk + 100
         )
 
+        # A multi-table inherited instance is never cosidered equal to
+        # its base class instances.
+        w = Worker(pk=1)
+        sw = StudentWorker(pk=1)
+        self.assertFalse(w==sw)
+        # The __eq__ operator is symmetric as well as the '==' operator
+        self.assertFalse(sw==w)
+        self.assertFalse(w.__eq__(sw))
+        self.assertFalse(sw.__eq__(w))
+
     def test_multiple_table(self):
         post = Post.objects.create(title="Lorem Ipsum")
         # The Post model has distinct accessors for the Comment and Link models.
diff --git a/tests/modeltests/proxy_models/tests.py b/tests/modeltests/proxy_models/tests.py
index 0a46a25..a4c7d40 100644
--- a/tests/modeltests/proxy_models/tests.py
+++ b/tests/modeltests/proxy_models/tests.py
@@ -45,6 +45,18 @@ class ProxyModelTests(TestCase):
         self.assertEqual(MyPerson.objects.get(name="Foo McBar").id, person.id)
         self.assertFalse(MyPerson.objects.get(id=person.id).has_special_name())
 
+    def test_proxy_eq(self):
+        """
+        Proxied models are considered equal to their concrete base class.
+        """
+        p = Person(pk=1)
+        mp = MyPerson(pk=1)
+        self.assertTrue(p==mp)
+        # the __eq__ operator is symmetric as well as the == operator
+        self.assertTrue(mp==p)
+        self.assertTrue(p.__eq__(mp))
+        self.assertTrue(mp.__eq__(p))
+
     def test_no_proxy(self):
         """
         Person is not proxied by StatusPerson subclass.
