diff --git a/django/contrib/admin/loading.py b/django/contrib/admin/loading.py
new file mode 100644
index 0000000..4481a13
--- /dev/null
+++ b/django/contrib/admin/loading.py
@@ -0,0 +1,21 @@
+
+class ModelAdminCache(object):
+    """
+    A cache of ModelAdmin classes. This ensures that once a ModelAdmin is
+    declared that it will remain the sole class. Basically providing a
+    guranteed ModelAdmin idenity.
+    """
+    def __init__(self):
+        self.modeladmin_store = {}
+    
+    def get(self, key):
+        return self.modeladmin_store[key]
+    
+    def register(self, *admin_classes):
+        for admin_class in admin_classes:
+            key = ".".join(admin_class.__module__.split(".")[-2:] + [admin_class.__name__])
+            if key in self.modeladmin_store:
+                continue
+            self.modeladmin_store[key] = admin_class
+
+admin_class_cache = ModelAdminCache()
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 29ce10a..228c529 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -4,6 +4,7 @@ from django.newforms.formsets import all_valid
 from django.newforms.models import _modelform_factory, _inlineformset_factory
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.admin import widgets
+from django.contrib.admin.loading import admin_class_cache
 from django.contrib.admin.util import get_deleted_objects
 from django.core.exceptions import ImproperlyConfigured, PermissionDenied
 from django.db import models, transaction
@@ -124,6 +125,21 @@ class AdminField(object):
         attrs = classes and {'class': u' '.join(classes)} or {}
         return self.field.label_tag(contents=contents, attrs=attrs)
 
+class ModelAdminMetaclass(type):
+    def __new__(cls, name, bases, attrs):
+        new_class = forms.MediaDefiningClass.__new__(cls, name, bases, attrs)
+        try:
+            parents = [b for b in bases if issubclass(b, ModelAdmin)]
+            if not parents:
+                return new_class
+        except NameError:
+            return new_class
+        # put this in some sort of registry
+        admin_class_cache.register(new_class)
+        # due to the way imports happening only use the admin class that is
+        # already registered.
+        return admin_class_cache.get(".".join(new_class.__module__.split(".")[-2:] + [new_class.__name__]))
+
 class BaseModelAdmin(object):
     """Functionality common to both ModelAdmin and InlineAdmin."""
     raw_id_fields = ()
@@ -200,7 +216,7 @@ class BaseModelAdmin(object):
 
 class ModelAdmin(BaseModelAdmin):
     "Encapsulates all admin options and functionality for a given model."
-    __metaclass__ = forms.MediaDefiningClass
+    __metaclass__ = ModelAdminMetaclass
 
     list_display = ('__str__',)
     list_display_links = ()
diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
index 6c6f47e..b496fb7 100644
--- a/django/contrib/admin/sites.py
+++ b/django/contrib/admin/sites.py
@@ -76,8 +76,8 @@ class AdminSite(object):
         if isinstance(model_or_iterable, ModelBase):
             model_or_iterable = [model_or_iterable]
         for model in model_or_iterable:
-            if model in self._registry:
-                raise AlreadyRegistered('The model %s is already registered' % model.__name__)
+            if model in self._registry and self._registry[model].__class__ is not admin_class:
+                raise AlreadyRegistered('The model %s is already registered to %s' % (model.__name__, self._registry[model].__class__.__name__))
             self._registry[model] = admin_class(model, self)
 
     def unregister(self, model_or_iterable):
diff --git a/tests/regressiontests/modeladmin/models.py b/tests/regressiontests/modeladmin/models.py
index 5e67c87..0a04691 100644
--- a/tests/regressiontests/modeladmin/models.py
+++ b/tests/regressiontests/modeladmin/models.py
@@ -17,6 +17,25 @@ we'll just pass in None.
 
 >>> request = None
 
+Ensure that only the first ModelAdmin ever declared is the only one for the
+app.
+
+>>> class OneBandAdmin(ModelAdmin):
+...     pass
+
+>>> class TwoBandAdmin(ModelAdmin):
+...     pass
+
+>>> one_band_admin_id = id(OneBandAdmin)
+>>> id(OneBandAdmin) != id(TwoBandAdmin)
+True
+
+>>> class OneBandAdmin(ModelAdmin):
+...     pass
+
+>>> one_band_admin_id == id(OneBandAdmin)
+True
+
 >>> band = Band(name='The Doors', bio='')
 
 Under the covers, the admin system will initialize ModelAdmin with a Model
@@ -96,10 +115,10 @@ properly. This won't, however, break any of the admin widgets or media.
 ...     class Meta:
 ...         model = Band
 
->>> class BandAdmin(ModelAdmin):
+>>> class AnotherBandAdmin(ModelAdmin):
 ...     form = AdminBandForm
 
->>> ma = BandAdmin(Band, site)
+>>> ma = AnotherBandAdmin(Band, site)
 >>> ma.get_form(request).base_fields.keys()
 ['name', 'bio', 'sign_date', 'delete']
 >>> type(ma.get_form(request).base_fields['sign_date'].widget)
