diff --git a/django/forms/models.py b/django/forms/models.py
index 6acd32c..112a2ff 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -202,6 +202,39 @@ class BaseModelForm(BaseForm):
             object_data.update(initial)
         super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
                                             error_class, label_suffix, empty_permitted)
+    def clean(self):
+        self.validate_unique()
+        return self.cleaned_data
+    
+    def validate_unique(self):
+        from django.db.models.fields import FieldDoesNotExist
+        unique_checks = self.instance._meta.unique_together[:]
+        form_errors = []
+        for name, field in self.fields.items():
+            try:
+                if name in self.cleaned_data and self.instance._meta.get_field_by_name(name)[0].unique and not self.instance._meta.get_field_by_name(name)[0].primary_key:
+                    unique_checks.append((name,))
+            except FieldDoesNotExist:
+                # This is an extra field that's not on the model, ignore it
+                pass
+        for unique_check in [check for check in unique_checks if not any([x in self._errors for x in check])]:
+            kwargs = dict([(field_name, self.cleaned_data[field_name]) for field_name in unique_check])
+            qs = self.instance.__class__._default_manager.filter(**kwargs)
+            if self.instance.pk is not None:
+                qs = qs.exclude(pk=self.instance.pk)
+            if qs.count() != 0:
+                model_name = self.instance._meta.verbose_name.title()
+                if len(unique_check) == 1:
+                    field_name = unique_check[0]
+                    field_label = self.fields[field_name].label
+                    self._errors[field_name] = ErrorList(["%s with this %s already exists." % (model_name, field_label)])
+                else:
+                    field_labels = [self.fields[field_name].label for field_name in unique_check]
+                    form_errors.append("%s with this %s already exists." % (model_name, ' and '.join(field_labels)))
+                for field_name in unique_check:
+                    del self.cleaned_data[field_name]
+        if form_errors:
+            raise ValidationError(form_errors)
 
     def save(self, commit=True):
         """
diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt
index d161b3f..163c428 100644
--- a/docs/topics/forms/modelforms.txt
+++ b/docs/topics/forms/modelforms.txt
@@ -338,6 +338,16 @@ parameter when declaring the form field::
    ...     class Meta:
    ...         model = Article
 
+Overriding the clean() method
+-----------------------------
+
+You can overide the ``clean()`` method on a model form to provide additional 
+validation in the same way you can on a normal form.  However, by default the 
+``clean()`` method validates the uniqueness of fields that are marked as unique
+on the model, and those marked as unque_together, if you would like to overide 
+the ``clean()`` method and maintain the default validation you must call the 
+parent class's ``clean()`` method.
+
 Form inheritance
 ----------------
 
@@ -500,4 +510,4 @@ books of a specific author. Here is how you could accomplish this::
     >>> from django.forms.models import inlineformset_factory
     >>> BookFormSet = inlineformset_factory(Author, Book)
     >>> author = Author.objects.get(name=u'Orson Scott Card')
-    >>> formset = BookFormSet(instance=author)
\ No newline at end of file
+    >>> formset = BookFormSet(instance=author)
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
index 5f714fb..a74b3d3 100644
--- a/tests/modeltests/model_forms/models.py
+++ b/tests/modeltests/model_forms/models.py
@@ -117,9 +117,20 @@ class CommaSeparatedInteger(models.Model):
     def __unicode__(self):
         return self.field
 
+class Unique(models.Model):
+    unique_field = models.CharField(max_length=100, unique=True)
+
+class UniqueTogether(models.Model):
+    unique_field_1 = models.CharField(max_length=100)
+    unique_field_2 = models.CharField(max_length=100)
+    
+    class Meta:
+        unique_together = (('unique_field_1', 'unique_field_2'),)
+
 class ArticleStatus(models.Model):
     status = models.CharField(max_length=2, choices=ARTICLE_STATUS_CHAR, blank=True, null=True)
 
+
 __test__ = {'API_TESTS': """
 >>> from django import forms
 >>> from django.forms.models import ModelForm, model_to_dict
@@ -1132,8 +1143,40 @@ u'1,,2'
 >>> f.clean('1')
 u'1'
 
-# Choices on CharField and IntegerField
+>>> class UniqueForm(ModelForm):
+...     class Meta:
+...         model = Unique
+>>> form1 = UniqueForm({'unique_field': 'unique'})
+>>> form1.is_valid()
+True
+>>> obj = form1.save()
+>>> obj
+<Unique: Unique object>
+>>> form2 = UniqueForm({'unique_field': 'unique'})
+>>> form2.is_valid()
+False
+>>> form2._errors
+{'unique_field': [u'Unique with this Unique field already exists.']}
+>>> form3 = UniqueForm({'unique_field': 'unique'}, instance=obj)
+>>> form3.is_valid()
+True
 
+# ModelForm test of unique_together constraint
+>>> class UniqueTogetherForm(ModelForm):
+...     class Meta:
+...         model = UniqueTogether
+>>> form1 = UniqueTogetherForm({'unique_field_1': 'unique1', 'unique_field_2': 'unique2'})
+>>> form1.is_valid()
+True
+>>> form1.save()
+<UniqueTogether: UniqueTogether object>
+>>> form2 = UniqueTogetherForm({'unique_field_1': 'unique1', 'unique_field_2': 'unique2'})
+>>> form2.is_valid()
+False
+>>> form2._errors
+{'__all__': [u'Unique Together with this Unique field 1 and Unique field 2 already exists.']}
+
+# Choices on CharField and IntegerField
 >>> class ArticleForm(ModelForm):
 ...     class Meta:
 ...         model = Article
