diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md
index 69a72a4..32dc7f6 100644
--- a/framework/CHANGELOG.md
+++ b/framework/CHANGELOG.md
@@ -173,6 +173,7 @@ Yii Framework 2 Change Log
 - Enh #4566: Added client validation support for image validator (Skysplit, qiangxue)
 - Enh #4581: Added ability to disable url encoding in `UrlRule` (tadaszelvys)
 - Enh #4602: Added $key param in ActionColumn buttons Closure call (disem)
+- Enh #4630: Added automatic generating of unique slug value to `yii\behaviors\Sluggable` (klimov-paul)
 - Enh: Added support for using sub-queries when building a DB query with `IN` condition (qiangxue)
 - Enh: Supported adding a new response formatter without the need to reconfigure existing formatters (qiangxue)
 - Enh: Added `yii\web\UrlManager::addRules()` to simplify adding new URL rules (qiangxue)
diff --git a/framework/behaviors/SluggableBehavior.php b/framework/behaviors/SluggableBehavior.php
index 8dd0a12..6703891 100644
--- a/framework/behaviors/SluggableBehavior.php
+++ b/framework/behaviors/SluggableBehavior.php
@@ -7,6 +7,8 @@
 
 namespace yii\behaviors;
 
+use yii\base\DynamicModel;
+use yii\base\Exception;
 use yii\base\InvalidConfigException;
 use yii\db\BaseActiveRecord;
 use yii\helpers\Inflector;
@@ -47,6 +49,7 @@ use yii\helpers\Inflector;
  * }
  * ```
  * @author Alexander Kochetov <creocoder@gmail.com>
+ * @author Paul Klimov <klimov.paul@gmail.com>
  * @since 2.0
  */
 class SluggableBehavior extends AttributeBehavior
@@ -56,11 +59,11 @@ class SluggableBehavior extends AttributeBehavior
      */
     public $slugAttribute = 'slug';
     /**
-     * @var string the attribute whose value will be converted into a slug
+     * @var string|array the attribute or list of attributes whose value will be converted into a slug
      */
     public $attribute;
     /**
-     * @var string|callable the value that will be used as a slug. This can be an anonymous function
+     * @var mixed the value that will be used as a slug. This can be an anonymous function
      * or an arbitrary value. If the former, the return value of the function will be used as a slug.
      * The signature of the function should be as follows,
      *
@@ -72,6 +75,39 @@ class SluggableBehavior extends AttributeBehavior
      * ```
      */
     public $value;
+    /**
+     * @var boolean whether to ensure generated slug value to be unique among owner class records.
+     * If enabled behavior will validate slug uniqueness automatically. If validation fails it will attempt
+     * generating unique slug value from based one until success.
+     */
+    public $unique = false;
+    /**
+     * @var array configuration for slug uniqueness validator. This configuration should not contain validator name
+     * and validated attributes - only options in format 'name => value' are allowed.
+     * For example:
+     * [
+     *     'filter' => ['type' => 1, 'status' => 2]
+     * ]
+     * @see yii\validators\UniqueValidator
+     */
+    public $uniqueValidatorConfig = [];
+    /**
+     * @var string|callable slug unique value generator. It is used in case [[unique]] enabled and generated
+     * slug is not unique. This can be a PHP callable with following signature:
+     *
+     * ```php
+     * function ($baseSlug, $iteration)
+     * {
+     *     // return uniqueSlug
+     * }
+     * ```
+     *
+     * Also one of the following predefined values can be used:
+     *  - 'increment' - adds incrementing suffix to the base slug
+     *  - 'uniqueid' - adds part of uniqueId hash string to the base slug
+     *  - 'timestamp' - adds current UNIX timestamp to the base slug
+     */
+    public $uniqueSlugGenerator = 'increment';
 
 
     /**
@@ -96,9 +132,112 @@ class SluggableBehavior extends AttributeBehavior
     protected function getValue($event)
     {
         if ($this->attribute !== null) {
-            $this->value = Inflector::slug($this->owner->{$this->attribute});
+            if (is_array($this->attribute)) {
+                $slugParts = [];
+                foreach ($this->attribute as $attribute) {
+                    $slugParts[] = Inflector::slug($this->owner->{$attribute});
+                }
+                $this->value = implode('-', $slugParts);
+            } else {
+                $this->value = Inflector::slug($this->owner->{$this->attribute});
+            }
+        }
+        $slug = parent::getValue($event);
+
+        if ($this->unique) {
+            $baseSlug = $slug;
+            $iteration = 0;
+            while (!$this->validateSlugUnique($slug)) {
+                $iteration++;
+                $slug = $this->generateUniqueSlug($baseSlug, $iteration);
+            }
         }
+        return $slug;
+    }
+
+    /**
+     * Checks if given slug value is unique.
+     * @param string $slug slug value
+     * @return boolean whether slug is unique.
+     */
+    private function validateSlugUnique($slug)
+    {
+        $validator = array_merge(
+            [
+                ['slug'],
+                'unique',
+                'targetClass' => get_class($this->owner)
+            ],
+            $this->uniqueValidatorConfig
+        );
+        $model = DynamicModel::validateData(compact('slug'), [$validator]);
+        return !$model->hasErrors();
+    }
 
-        return parent::getValue($event);
+    /**
+     * @param string $baseSlug base slug value
+     * @param integer $iteration iteration number
+     * @return string slug suffix
+     * @throws \yii\base\InvalidConfigException
+     */
+    private function generateUniqueSlug($baseSlug, $iteration)
+    {
+        $generator = $this->uniqueSlugGenerator;
+        switch ($generator) {
+            case 'increment':
+                return $this->generateUniqueSlugIncrement($baseSlug, $iteration);
+            case 'uniqueid':
+                return $this->generateUniqueSlugUniqueId($baseSlug, $iteration);
+            case 'timestamp':
+                return $this->generateSuffixSlugTimestamp($baseSlug, $iteration);
+            default:
+                if (is_callable($generator)) {
+                    return call_user_func($generator, $baseSlug, $iteration);
+                }
+                throw new InvalidConfigException("Unrecognized slug unique suffix generator '{$generator}'.");
+        }
+    }
+
+    /**
+     * Generates slug using increment of iteration.
+     * @param string $baseSlug base slug value
+     * @param integer $iteration iteration number
+     * @return string generated suffix.
+     */
+    protected function generateUniqueSlugIncrement($baseSlug, $iteration)
+    {
+        return $baseSlug . '-' . ($iteration + 1);
+    }
+
+    /**
+     * Generates slug using unique id.
+     * @param string $baseSlug base slug value
+     * @param integer $iteration iteration number
+     * @throws \yii\base\Exception
+     * @return string generated suffix.
+     */
+    protected function generateUniqueSlugUniqueId($baseSlug, $iteration)
+    {
+        static $uniqueId;
+        if ($iteration < 2) {
+            $uniqueId = sha1(uniqid(get_class($this), true));
+        }
+        $subStringLength = 6 + $iteration;
+        if ($subStringLength > strlen($uniqueId)) {
+            throw new Exception('Unique id is exhausted.');
+        }
+        return $baseSlug . '-' . substr($uniqueId, 0, $subStringLength);
+    }
+
+    /**
+     * Generates slug using current timestamp.
+     * @param string $baseSlug base slug value
+     * @param integer $iteration iteration number
+     * @throws \yii\base\Exception
+     * @return string generated suffix.
+     */
+    protected function generateSuffixSlugTimestamp($baseSlug, $iteration)
+    {
+        return $baseSlug . '-' . (time() + $iteration - 1);
     }
 }
diff --git a/tests/unit/framework/behaviors/SluggableBehaviorTest.php b/tests/unit/framework/behaviors/SluggableBehaviorTest.php
new file mode 100644
index 0000000..861b400
--- /dev/null
+++ b/tests/unit/framework/behaviors/SluggableBehaviorTest.php
@@ -0,0 +1,197 @@
+<?php
+
+namespace yiiunit\framework\behaviors;
+
+use Yii;
+use yiiunit\TestCase;
+use yii\db\Connection;
+use yii\db\ActiveRecord;
+use yii\behaviors\SluggableBehavior;
+
+/**
+ * Unit test for [[\yii\behaviors\SluggableBehavior]].
+ * @see SluggableBehavior
+ *
+ * @group behaviors
+ */
+class SluggableBehaviorTest extends TestCase
+{
+    /**
+     * @var Connection test db connection
+     */
+    protected $dbConnection;
+
+    public static function setUpBeforeClass()
+    {
+        if (!extension_loaded('pdo') || !extension_loaded('pdo_sqlite')) {
+            static::markTestSkipped('PDO and SQLite extensions are required.');
+        }
+    }
+
+    public function setUp()
+    {
+        $this->mockApplication([
+            'components' => [
+                'db' => [
+                    'class' => '\yii\db\Connection',
+                    'dsn' => 'sqlite::memory:',
+                ]
+            ]
+        ]);
+
+        $columns = [
+            'id' => 'pk',
+            'name' => 'string',
+            'slug' => 'string',
+            'category_id' => 'integer',
+        ];
+        Yii::$app->getDb()->createCommand()->createTable('test_slug', $columns)->execute();
+    }
+
+    public function tearDown()
+    {
+        Yii::$app->getDb()->close();
+        parent::tearDown();
+    }
+
+    // Tests :
+
+    public function testSlug()
+    {
+        $model = new ActiveRecordSluggable();
+        $model->name = 'test name';
+        $model->validate();
+
+        $this->assertEquals('test-name', $model->slug);
+    }
+
+    /**
+     * @depends testSlug
+     */
+    public function testSlugSeveralAttributes()
+    {
+        $model = new ActiveRecordSluggable();
+        $model->getBehavior('sluggable')->attribute = array('name', 'category_id');
+
+        $model->name = 'test';
+        $model->category_id = 10;
+
+        $model->validate();
+        $this->assertEquals('test-10', $model->slug);
+    }
+
+    /**
+     * @depends testSlug
+     */
+    public function testUniqueByIncrement()
+    {
+        $name = 'test name';
+
+        $model = new ActiveRecordSluggable();
+        $model->name = $name;
+        $model->save();
+
+        $model = new ActiveRecordSluggable();
+        $model->sluggable->unique = true;
+        $model->name = $name;
+        $model->save();
+
+        $this->assertEquals('test-name-2', $model->slug);
+    }
+
+    /**
+     * @depends testUniqueByIncrement
+     */
+    public function testUniqueByCallback()
+    {
+        $name = 'test name';
+
+        $model = new ActiveRecordSluggable();
+        $model->name = $name;
+        $model->save();
+
+        $model = new ActiveRecordSluggable();
+        $model->sluggable->unique = true;
+        $model->sluggable->uniqueSlugGenerator = function($baseSlug, $iteration) {return $baseSlug . '-callback';};
+        $model->name = $name;
+        $model->save();
+
+        $this->assertEquals('test-name-callback', $model->slug);
+    }
+
+    /**
+     * @depends testUniqueByIncrement
+     */
+    public function testUniqueByUniqueId()
+    {
+        $name = 'test name';
+
+        $model1 = new ActiveRecordSluggable();
+        $model1->name = $name;
+        $model1->save();
+
+        $model2 = new ActiveRecordSluggable();
+        $model2->sluggable->unique = true;
+        $model2->sluggable->uniqueSlugGenerator = 'uniqueid';
+        $model2->name = $name;
+        $model2->save();
+
+        $this->assertNotEquals($model2->slug, $model1->slug);
+    }
+
+    /**
+     * @depends testUniqueByIncrement
+     */
+    public function testUniqueByTimestamp()
+    {
+        $name = 'test name';
+
+        $model1 = new ActiveRecordSluggable();
+        $model1->name = $name;
+        $model1->save();
+
+        $model2 = new ActiveRecordSluggable();
+        $model2->sluggable->unique = true;
+        $model2->sluggable->uniqueSlugGenerator = 'timestamp';
+        $model2->name = $name;
+        $model2->save();
+
+        $this->assertNotEquals($model2->slug, $model1->slug);
+    }
+}
+
+/**
+ * Test Active Record class with [[SluggableBehavior]] behavior attached.
+ *
+ * @property integer $id
+ * @property string $name
+ * @property string $slug
+ * @property integer $category_id
+ *
+ * @property SluggableBehavior $sluggable
+ */
+class ActiveRecordSluggable extends ActiveRecord
+{
+    public function behaviors()
+    {
+        return [
+            'sluggable' => [
+                'class' => SluggableBehavior::className(),
+                'attribute' => 'name',
+            ],
+        ];
+    }
+
+    public static function tableName()
+    {
+        return 'test_slug';
+    }
+
+    /**
+     * @return SluggableBehavior
+     */
+    public function getSluggable()
+    {
+        return $this->getBehavior('sluggable');
+    }
+}
\ No newline at end of file