diff --git a/feeds.api.php b/feeds.api.php
index 14a8555..6ee490a 100644
--- a/feeds.api.php
+++ b/feeds.api.php
@@ -271,10 +271,10 @@ function my_source_get_source(FeedsSource $source, FeedsParserResult $result, $k
  *   Remove with caution.
  * @param $entity_type
  *   The entity type of the target, for instance a 'node' entity.
- * @param $bundle_name
+ * @param $bundle
  *   The bundle name for which to alter targets.
  */
-function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) {
   if ($entity_type == 'node') {
     $targets['my_node_field'] = array(
       'name' => t('My custom node field'),
@@ -292,6 +292,17 @@ function hook_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_nam
       'callback' => 'my_module_set_target2',
       'real_target' => 'my_node_field_two', // Specify real target field on node.
     );
+    $targets['my_node_field3'] = array(
+      'name' => t('My third custom node field'),
+      'description' => t('Description of what my third custom node field does.'),
+      'callback' => 'my_module_set_target3',
+
+      // Set optional_unique to TRUE and specify unique_callbacks to allow the
+      // target to be unique. Existing entities can be updated based on unique
+      // targets.
+      'optional_unique' => TRUE,
+      'unique_callbacks' => array('my_module_mapper_unique'),
+    );
   }
 }
 
@@ -369,5 +380,40 @@ function my_module_form_callback($mapping, $target, $form, $form_state) {
 }
 
 /**
+ * Example of the unique_callbacks specified in
+ * hook_feeds_processor_targets_alter().
+ *
+ * @param FeedsSource $source
+ *   The Feed source.
+ * @param string $entity_type
+ *   Entity type for the entity to be processed.
+ * @param string $bundle
+ *   Bundle name for the entity to be processed.
+ * @param string $target
+ *   A string identifying the unique target on the entity.
+ * @param array $values
+ *   The unique values to be checked.
+ *
+ * @return int
+ *   The existing entity id, or 0 if not found.
+ *
+ * @see hook_feeds_processor_targets_alter()
+ * @see FeedsProcessor::existingEntityId()
+ */
+function my_module_mapper_unique(FeedsSource $source, $entity_type, $bundle, $target, array $values) {
+  list($field_name, $column) = explode(':', $target . ':value');
+  // Example for if the target is a field.
+  $query = new EntityFieldQuery();
+  $result = $query->entityCondition('entity_type', $entity_type)
+                  ->entityCondition('bundle', $bundle)
+                  ->fieldCondition($field_name, $column, $values)
+                  ->execute();
+
+  if (!empty($result[$entity_type])) {
+    return key($result[$entity_type]);
+  }
+}
+
+/**
  * @}
  */
diff --git a/feeds.info b/feeds.info
index ec2ffda..bc5028d 100644
--- a/feeds.info
+++ b/feeds.info
@@ -38,6 +38,7 @@ files[] = tests/feeds_mapper_field.test
 files[] = tests/feeds_mapper_file.test
 files[] = tests/feeds_mapper_path.test
 files[] = tests/feeds_mapper_profile.test
+files[] = tests/feeds_mapper_unique.test
 files[] = tests/feeds_mapper.test
 files[] = tests/feeds_mapper_config.test
 files[] = tests/feeds_fetcher_file.test
diff --git a/plugins/FeedsProcessor.inc b/plugins/FeedsProcessor.inc
index 6666276..d197b08 100755
--- a/plugins/FeedsProcessor.inc
+++ b/plugins/FeedsProcessor.inc
@@ -738,10 +738,10 @@ abstract class FeedsProcessor extends FeedsPlugin {
    *
    * @param FeedsSource $source
    *   The source information about this import.
-   * @param $result
+   * @param FeedsParserResult $result
    *   A FeedsParserResult object.
    *
-   * @return
+   * @return int
    *   The serial id of an entity if found, 0 otherwise.
    */
   protected function existingEntityId(FeedsSource $source, FeedsParserResult $result) {
@@ -751,23 +751,40 @@ abstract class FeedsProcessor extends FeedsPlugin {
       ->condition('entity_type', $this->entityType())
       ->condition('id', $source->id);
 
-    // Iterate through all unique targets and test whether they do already
-    // exist in the database.
+    static $targets = array();
+    if (!isset($targets[$this->id])) {
+      $targets[$this->id] = $this->getMappingTargets();
+    }
+
+    $entity_id = 0;
+
+    // Iterate through all unique targets and test whether they already exist in
+    // the database.
     foreach ($this->uniqueTargets($source, $result) as $target => $value) {
-      switch ($target) {
-        case 'url':
-          $entity_id = $query->condition('url', $value)->execute()->fetchField();
-          break;
-        case 'guid':
-          $entity_id = $query->condition('guid', $value)->execute()->fetchField();
-          break;
+      if ($target === 'guid' || $target === 'url') {
+        $entity_id = $query->condition($target, $value)->execute()->fetchField();
       }
-      if (isset($entity_id)) {
-        // Return with the content id found.
+
+      if (!$entity_id && !empty($targets[$this->id][$target]['unique_callbacks'])) {
+        if (!is_array($value)) {
+          $value = array($value);
+        }
+
+        foreach ($targets[$this->id][$target]['unique_callbacks'] as $callback) {
+          if (is_callable($callback) && $entity_id = call_user_func_array($callback, array($source, $this->entityType(), $this->bundle(), $target, $value))) {
+            // Stop at the first unique ID returned by a callback.
+            break;
+          }
+        }
+      }
+
+      // Return with the content id found.
+      if ($entity_id) {
         return $entity_id;
       }
     }
-    return 0;
+
+    return $entity_id;
   }
 
 
diff --git a/tests/feeds_mapper_unique.test b/tests/feeds_mapper_unique.test
new file mode 100644
index 0000000..9d0e4a7
--- /dev/null
+++ b/tests/feeds_mapper_unique.test
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Conatins FeedsMapperUniqueTestCase.
+ */
+
+/**
+ * Class for testing Feeds unique callbacks.
+ */
+class FeedsMapperUniqueTestCase extends FeedsMapperTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Unique target callbacks',
+      'description' => 'Test unique target callbacks in mappers.',
+      'group' => 'Feeds',
+    );
+  }
+
+  /**
+   * Test mapping target "unique_callbacks".
+   */
+  public function test() {
+    // Create content type.
+    $typename = $this->createContentType(array(), array('alpha' => 'text'));
+
+    // Create two nodes. Put unique value into field field_alpha.
+    $node1 = $this->drupalCreateNode(array(
+      'type' => $typename,
+      'field_alpha' => array(
+        LANGUAGE_NONE => array(
+          0 => array(
+            'value' => 'Ut wisi',
+          ),
+        ),
+      ),
+    ));
+    $node2 = $this->drupalCreateNode(array(
+      'type' => $typename,
+      'field_alpha' => array(
+        LANGUAGE_NONE => array(
+          0 => array(
+            'value' => 'Lorem',
+          ),
+        ),
+      ),
+    ));
+
+    // Create and configure importer.
+    $this->createImporterConfiguration('Syndication', 'syndication');
+    $this->setPlugin('syndication', 'FeedsFileFetcher');
+    $this->setPlugin('syndication', 'FeedsCSVParser');
+    $this->setSettings('syndication', 'FeedsNodeProcessor', array('bundle' => $typename, 'update_existing' => 2));
+    $this->addMappings('syndication', array(
+      0 => array(
+        'source' => 'title',
+        'target' => 'title',
+      ),
+      1 => array(
+        'source' => 'alpha',
+        'target' => 'test_unique_target',
+        'unique' => TRUE,
+      ),
+    ));
+
+    // Import CSV file.
+    $this->importFile('syndication', $this->absolutePath() . '/tests/feeds/content.csv');
+    $this->assertText('Updated 2 nodes');
+
+    // Ensure the updated nodes have the expected title now.
+    $node1 = node_load($node1->nid, NULL, TRUE);
+    $this->assertEqual('Ut wisi enim ad minim veniam', $node1->title, 'Node 1 has the expected title');
+    $node2 = node_load($node2->nid, NULL, TRUE);
+    $this->assertEqual('Lorem ipsum', $node2->title, 'Node 2 has the expected title');
+  }
+
+}
diff --git a/tests/feeds_tests.module b/tests/feeds_tests.module
index 399708b..6c96ccf 100644
--- a/tests/feeds_tests.module
+++ b/tests/feeds_tests.module
@@ -104,7 +104,7 @@ function feeds_tests_files_remote() {
 /**
  * Implements hook_feeds_processor_targets_alter().
  */
-function feeds_tests_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+function feeds_tests_feeds_processor_targets_alter(&$targets, $entity_type, $bundle) {
   $targets['test_target'] = array(
     'name' => t('Test Target'),
     'description' => t('This is a test target.'),
@@ -112,6 +112,14 @@ function feeds_tests_feeds_processor_targets_alter(&$targets, $entity_type, $bun
     'summary_callback' => 'feeds_tests_mapper_summary',
     'form_callback' => 'feeds_tests_mapper_form',
   );
+
+  $targets['test_unique_target'] = array(
+    'name' => t('Test unique target'),
+    'description' => t('This is a unique test target.'),
+    'callback' => 'feeds_tests_mapper_set_target',
+    'optional_unique' => TRUE,
+    'unique_callbacks' => array('feeds_tests_mapper_unique'),
+  );
 }
 
 /**
@@ -205,3 +213,20 @@ function feeds_tests_mapper_form($mapping, $target, $form, $form_state) {
     ),
   );
 }
+
+/**
+ * Callback for unique_callbacks for test_target mapper.
+ *
+ * @see feeds_tests_feeds_processor_targets_alter()
+ */
+function feeds_tests_mapper_unique(FeedsSource $source, $entity_type, $bundle, $target, array $values) {
+  $query = new EntityFieldQuery();
+  $result = $query->entityCondition('entity_type', $entity_type)
+                  ->entityCondition('bundle', $bundle)
+                  ->fieldCondition('field_alpha', 'value', $values)
+                  ->execute();
+
+  if (!empty($result[$entity_type])) {
+    return key($result[$entity_type]);
+  }
+}
