Index: django/forms/models.py
===================================================================
--- django/forms/models.py	(revision 8382)
+++ django/forms/models.py	(working copy)
@@ -201,6 +201,29 @@
         super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
                                             error_class, label_suffix, empty_permitted)
 
+    def clean(self):
+        unique_checks = self.instance._meta.unique_together[:]
+        form_errors = []
+        for name, field in self.fields.items():
+            if name in self.cleaned_data and self.instance._meta.get_field_by_name(name)[0].unique:
+                unique_checks.append((name,))
+        for unique_check in unique_checks:
+            kwargs = dict([(field_name, self.cleaned_data[field_name]) for field_name in unique_check])
+            if self.instance._default_manager.filter(**kwargs).exclude(pk=self.instance.id).count() != 0:
+                model_name = type(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:
+                    self.cleaned_data.pop(field_name, '')
+        if form_errors:
+            raise ValidationError, form_errors
+        return self.cleaned_data
+    
     def save(self, commit=True):
         """
         Saves this ``form``'s cleaned_data into model instance
Index: tests/modeltests/model_forms/models.py
===================================================================
--- tests/modeltests/model_forms/models.py	(revision 8382)
+++ tests/modeltests/model_forms/models.py	(working copy)
@@ -83,6 +83,17 @@
     def __unicode__(self):
         return self.description
 
+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'),)
+
+
 __test__ = {'API_TESTS': """
 >>> from django import forms
 >>> from django.forms.models import ModelForm
@@ -1016,4 +1027,36 @@
 <link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
 <script type="text/javascript" src="/some/form/javascript"></script>
 
+# ModelForm test of unique constraint
+
+>>> class UniqueForm(ModelForm):
+...     class Meta:
+...         model = Unique
+>>> form1 = UniqueForm({'unique_field': 'unique'})
+>>> form1.is_valid()
+True
+>>> form1.save()
+<Unique: Unique object>
+>>> form2 = UniqueForm({'unique_field': 'unique'})
+>>> form2.is_valid()
+False
+>>> form2._errors
+{'unique_field': [u'Unique with this Unique field already exists.']}
+
+# 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.']}
+
 """}
